package yang.yu.sunny.domain;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.dayatang.domain.AbstractEntity;
import org.dayatang.domain.InstanceFactory;
import yang.yu.sunny.EventBus;

import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 产品类别
 * Created by yyang on 16/3/15.
 */
@Entity
@Table(name = "product_categories")
public class ProductCategory extends AbstractEntity {

    private String name;

    protected ProductCategory() {
    }

    public ProductCategory(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Optional<ProductCategory> getParent() {
        return new ProductCategoryService().getParentOf(this);
    }

    public List<ProductCategory> getChildren() {
        return new ProductCategoryService().getChildrenOf(this);
    }

    public ProductCategory createChild(String name) {
        ProductCategory child = new ProductCategory(name);
        child.save();
        new ProductCategoryRelation(this, child).save();
        return child;
    }

    public void changeName(String newName) {
        String oldName = name;
        name = newName;
        save();
        InstanceFactory.getInstance(EventBus.class)
                .post(new ProductCategoryNameChangedEvent(getId(), oldName, newName));
    }

    /**
     * 列出直属本类别的产品
     * @return
     */
    public List<Product> listProducts() {
        return Product.findByCategory(this);
    }

    /**
     * 列出本类别（包括下属类别）的所有产品
     * @return
     */
    public List<Product> listAllProducts() {
        List<Product> results = new ArrayList<>();
        results.addAll(Product.findByCategory(this));
        getChildren().stream().forEach(category -> {
            results.addAll(category.listAllProducts());});
        return results;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof ProductCategory)) {
            return false;
        }
        ProductCategory that = (ProductCategory) o;
        return new EqualsBuilder()
                .append(this.getId(), that.getId())
                .isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 37)
                .appendSuper(super.hashCode())
                .append(getId())
                .toHashCode();
    }

    @Override
    public String toString() {
        return getName();
    }

    public static ProductCategory get(Long id) {
        return getRepository().get(ProductCategory.class, id);
    }
}
